<!--
  - EditTransaction.vue
  - Copyright (c) 2019 james@firefly-iii.org
  -
  - This file is part of Firefly III (https://github.com/firefly-iii).
  -
  - This program is free software: you can redistribute it and/or modify
  - it under the terms of the GNU Affero General Public License as
  - published by the Free Software Foundation, either version 3 of the
  - License, or (at your option) any later version.
  -
  - This program is distributed in the hope that it will be useful,
  - but WITHOUT ANY WARRANTY; without even the implied warranty of
  - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  - GNU Affero General Public License for more details.
  -
  - You should have received a copy of the GNU Affero General Public License
  - along with this program.  If not, see <https://www.gnu.org/licenses/>.
  -->

<template>
  <form id="store" accept-charset="UTF-8" action="#" class="form-horizontal" enctype="multipart/form-data"
        method="POST">
    <input name="_token" type="hidden" value="xxx">
    <div v-if="error_message !== ''" class="row">
      <div class="col-lg-12">
        <div class="alert alert-danger alert-dismissible" role="alert">
          <button class="close" data-dismiss="alert" type="button" v-bind:aria-label="$t('firefly.close')"><span
              aria-hidden="true">&times;</span></button>
          <strong>{{ $t("firefly.flash_error") }}</strong> {{ error_message }}
        </div>
      </div>
    </div>

    <div v-if="success_message !== ''" class="row">
      <div class="col-lg-12">
        <div class="alert alert-success alert-dismissible" role="alert">
          <button class="close" data-dismiss="alert" type="button" v-bind:aria-label="$t('firefly.close')"><span
              aria-hidden="true">&times;</span></button>
          <strong>{{ $t("firefly.flash_success") }}</strong> <span v-html="success_message"></span>
        </div>
      </div>
    </div>
    <div>
      <div v-for="(transaction, index) in transactions" class="row">
        <div class="col-lg-12">
          <div class="box">
            <div class="box-header with-border">
              <h3 class="box-title splitTitle">
                <span v-if="transactions.length > 1">{{ $t('firefly.single_split') }} {{ index + 1 }} / {{
                    transactions.length
                  }}</span>
                <span v-if="transactions.length === 1">{{ $t('firefly.transaction_journal_information') }}</span>
              </h3>
              <div v-if="transactions.length > 1" class="box-tools pull-right">
                <button class="btn btn-xs btn-danger" type="button" v-on:click="deleteTransaction(index, $event)"><i
                    class="fa fa-trash"></i></button>
              </div>
            </div>
            <div class="box-body">
              <div class="row">
                <div class="col-lg-4">
                  <transaction-description v-if="transactionType.toLowerCase() !== 'reconciliation'"
                                           v-model="transaction.description"
                                           :error="transaction.errors.description"
                                           :index="index"
                  >
                  </transaction-description>
                  <account-select v-if="transactionType.toLowerCase() !== 'reconciliation'"
                                  :accountName="transaction.source_account.name"
                                  :accountTypeFilters="transaction.source_account.allowed_types"
                                  :error="transaction.errors.source_account"
                                  :index="index"
                                  :transactionType="transactionType"
                                  inputName="source[]"
                                  v-bind:inputDescription="$t('firefly.source_account')"
                                  v-on:clear:value="clearSource(index)"
                                  v-on:select:account="selectedSourceAccount(index, $event)"
                  ></account-select>
                  <div v-if="transactionType.toLowerCase() === 'reconciliation'" class="form-group">
                    <div class="col-sm-12">
                      <p id="ffInput_source" class="form-control-static">
                        <em>
                          {{ $t('firefly.source_account_reconciliation') }}
                        </em>
                      </p>
                    </div>
                  </div>
                  <account-select v-if="transactionType.toLowerCase() !== 'reconciliation'"
                                  :accountName="transaction.destination_account.name"
                                  :accountTypeFilters="transaction.destination_account.allowed_types"
                                  :error="transaction.errors.destination_account"
                                  :index="index"
                                  :transactionType="transactionType"
                                  inputName="destination[]"
                                  v-bind:inputDescription="$t('firefly.destination_account')"
                                  v-on:clear:value="clearDestination(index)"
                                  v-on:select:account="selectedDestinationAccount(index, $event)"
                  ></account-select>
                  <div v-if="transactionType.toLowerCase() === 'reconciliation'" class="form-group">
                    <div class="col-sm-12">
                      <p id="ffInput_dest" class="form-control-static">
                        <em>
                          {{ $t('firefly.destination_account_reconciliation') }}
                        </em>
                      </p>
                    </div>
                  </div>
                  <standard-date
                      v-model="transaction.date"
                      :error="transaction.errors.date"
                      :index="index"
                  >
                  </standard-date>
                  <div v-if="index===0">
                    <transaction-type
                        :destination="transaction.destination_account.type"
                        :source="transaction.source_account.type"
                        v-on:set:transactionType="setTransactionType($event)"
                        v-on:act:limitSourceType="limitSourceType($event)"
                        v-on:act:limitDestinationType="limitDestinationType($event)"
                    ></transaction-type>
                  </div>
                </div>
                <div class="col-lg-4">
                  <!-- -->
                  <amount
                      v-model="transaction.amount"
                      :destination="transaction.destination_account"
                      :error="transaction.errors.amount"
                      :index="index"
                      :source="transaction.source_account"
                      :transactionType="transactionType"
                  ></amount>
                  <foreign-amount v-if="transactionType.toLowerCase() !== 'reconciliation'"
                                  v-model="transaction.foreign_amount"
                                  :destination="transaction.destination_account"
                                  :error="transaction.errors.foreign_amount"
                                  :no_currency="$t('firefly.none_in_select_list')"
                                  :source="transaction.source_account"
                                  :transactionType="transactionType"
                                  v-bind:title="$t('form.foreign_amount')"
                  ></foreign-amount>
                </div>
                <div class="col-lg-4">
                  <budget
                      v-model="transaction.budget"
                      :error="transaction.errors.budget_id"
                      :no_budget="$t('firefly.none_in_select_list')"
                      :transactionType="transactionType"
                  ></budget>
                  <category
                      v-model="transaction.category"
                      :error="transaction.errors.category"
                      :transactionType="transactionType"
                  ></category>
                  <tags
                      v-model="transaction.tags"
                      :error="transaction.errors.tags"
                      :tags="transaction.tags"
                      :transactionType="transactionType"
                  ></tags>
                  <bill
                      v-model="transaction.bill"
                      :error="transaction.errors.bill_id"
                      :no_bill="$t('firefly.none_in_select_list')"
                      :transactionType="transactionType"
                  ></bill>
                  <custom-transaction-fields
                      v-model="transaction.custom_fields"
                      :error="transaction.errors.custom_errors"
                  ></custom-transaction-fields>
                </div>
              </div>
            </div>
            <div v-if="transactions.length-1 === index && transactionType.toLowerCase() !== 'reconciliation'"
                 class="box-footer">
              <button class="btn btn-default" type="button" @click="addTransaction">{{
                  $t('firefly.add_another_split')
                }}
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div v-if="transactions.length > 1" class="row">
      <div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
        <div class="box">
          <div class="box-header with-border">
            <h3 class="box-title">
              {{ $t('firefly.split_transaction_title') }}
            </h3>
          </div>
          <div class="box-body">
            <group-description
                v-model="group_title"
                :error="group_title_errors"
            ></group-description>
          </div>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
        <div class="box">
          <div class="box-header with-border">
            <h3 class="box-title">
              {{ $t('firefly.submission') }}
            </h3>
          </div>
          <div class="box-body">
            <div class="checkbox">
              <label>
                <input v-model="returnAfter" name="return_after" type="checkbox">
                {{ $t('firefly.after_update_create_another') }}
              </label>
            </div>
            <div v-if="null !== transactionType && transactionType.toLowerCase() !== 'reconciliation'" class="checkbox">
              <label>
                <input v-model="storeAsNew" name="store_as_new" type="checkbox">
                {{ $t('firefly.store_as_new') }}
              </label>
            </div>
          </div>
          <div class="box-footer">
            <div class="btn-group">
              <button id="submitButton" class="btn btn-success" @click="submit">{{
                  $t('firefly.update_transaction')
                }}
              </button>
            </div>
          </div>
        </div>
      </div>
        <div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
          <div class="box">
            <div class="box-header with-border">
              <h3 class="box-title">
                {{ $t('firefly.submission_options') }}
              </h3>
            </div>
            <div class="box-body">
              <div class="checkbox">
                <label>
                  <input v-model="applyRules" name="apply_rules" type="checkbox">
                  {{ $t('firefly.apply_rules_checkbox') }}
                </label>
              </div>
              <div class="checkbox">
                <label>
                  <input v-model="fireWebhooks" name="fire_webhooks" type="checkbox">
                  {{ $t('firefly.fire_webhooks_checkbox') }}

                </label>
              </div>
            </div>
        </div>
      </div>
    </div>
  </form>
</template>

<script>
export default {
  name: "EditTransaction",
  props: {
    groupId: Number
  },
  mounted() {
    // console.log('EditTransaction: mounted()');
    this.getGroup();
  },
  ready() {
    // console.log('EditTransaction: ready()');
  },
  methods: {
    positiveAmount(amount) {
      if (amount < 0) {
        return amount * -1;
      }
      return amount;
    },
    roundNumber(amount, decimals) {
      let multiplier = Math.pow(10, decimals);
      return Math.round(amount * multiplier) / multiplier;
    },
    selectedSourceAccount(index, model) {
      if (typeof model === 'string') {
        // cant change types, only name.
        // also clear ID
        this.transactions[index].source_account.id = null;
        this.transactions[index].source_account.name = model;
        return;
      }
      this.transactions[index].source_account = {
        id: model.id,
        name: model.name,
        type: model.type,
        currency_id: model.currency_id,
        currency_name: model.currency_name,
        currency_code: model.currency_code,
        currency_decimal_places: model.currency_decimal_places,
        allowed_types: this.transactions[index].source_account.allowed_types
      };
    },
    selectedDestinationAccount(index, model) {
      if (typeof model === 'string') {
        // cant change types, only name.
        // also clear ID
        this.transactions[index].destination_account.id = null;
        this.transactions[index].destination_account.name = model;
        return;
      }
      this.transactions[index].destination_account = {
        id: model.id,
        name: model.name,
        type: model.type,
        currency_id: model.currency_id,
        currency_name: model.currency_name,
        currency_code: model.currency_code,
        currency_decimal_places: model.currency_decimal_places,
        allowed_types: this.transactions[index].destination_account.allowed_types
      };
    },
    clearSource(index) {
      // reset source account:
      this.transactions[index].source_account = {
        id: 0,
        name: '',
        type: '',
        currency_id: 0,
        currency_name: '',
        currency_code: '',
        currency_decimal_places: 2,
        allowed_types: this.transactions[index].source_account.allowed_types
      };
      // if there is a destination model, reset the types of the source
      // by pretending we selected it again.
      if (this.transactions[index].destination_account) {
        this.selectedDestinationAccount(index, this.transactions[index].destination_account);
      }
    },
    setTransactionType(type) {
      if (null !== type) {
        this.transactionType = type;
      }
    },
    deleteTransaction(index, event) {
      event.preventDefault();
      this.transactions.splice(index, 1);
    },
    clearDestination(index) {
      // console.log('clearDestination(' + index + ')');
      // reset destination account:
      // console.log('Destination allowed types first:');
      // console.log(this.transactions[index].destination_account.allowed_types);
      this.transactions[index].destination_account = {
        id: 0,
        name: '',
        type: '',
        currency_id: 0,
        currency_name: '',
        currency_code: '',
        currency_decimal_places: 2,
        allowed_types: this.transactions[index].destination_account.allowed_types
      };
      // reset destination allowed account types.
      //this.transactions[index].source_account.allowed_types = [];

      // if there is a source model, reset the types of the destination
      // by pretending we selected it again.
      if (this.transactions[index].source_account) {
        this.selectedSourceAccount(index, this.transactions[index].source_account);
      }

      // console.log('Destination allowed types after:');
      // console.log(this.transactions[index].destination_account.allowed_types);
    },
    getGroup() {
      // console.log('EditTransaction: getGroup()');
      const page = window.location.href.split('/');
      const groupId = page[page.length - 1];


      const uri = './api/v1/transactions/' + groupId;
      // console.log(uri);

      // fill in transactions array.
      axios.get(uri)
          .then(response => {
            this.processIncomingGroup(response.data.data);
          })
          .catch(error => {
            console.error('Some error when getting axios');
            console.error(error);
          });
    },
    processIncomingGroup(data) {
      // console.log('EditTransaction: processIncomingGroup()');
      this.group_title = data.attributes.group_title;
      let transactions = data.attributes.transactions.reverse();
      for (let key in transactions) {
        if (transactions.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
          let transaction = transactions[key];
          this.processIncomingGroupRow(transaction);
        }

      }
    },
    ucFirst(string) {
      if (typeof string === 'string') {
        return string.charAt(0).toUpperCase() + string.slice(1);
      }
      return null;
    },
    processIncomingGroupRow(transaction) {
      //console.log('EditTransaction: processIncomingGroupRow()');
      this.setTransactionType(transaction.type);

      let newTags = [];
      for (let key in transaction.tags) {
        if (transaction.tags.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
          newTags.push({text: transaction.tags[key], tiClasses: []});
        }
      }
      // console.log('source allowed types for a ' + transaction.type);
      //console.log(window.expectedSourceTypes.source[transaction.type]);
      // console.log(window.expectedSourceTypes.source[this.ucFirst(transaction.type)]);
      // console.log('destination allowed types for a ' + transaction.type);
      // console.log(window.expectedSourceTypes.destination[this.ucFirst(transaction.type)]);
      if (typeof window.expectedSourceTypes === 'undefined') {
        console.error('window.expectedSourceTypes is unexpectedly empty.')
      }

      this.transactions.push({
        transaction_journal_id: transaction.transaction_journal_id,
        description: transaction.description,
        date: transaction.date.substr(0, 10),
        amount: this.roundNumber(this.positiveAmount(transaction.amount), transaction.currency_decimal_places),
        category: transaction.category_name,
        errors: {
          source_account: [],
          destination_account: [],
          description: [],
          amount: [],
          date: [],
          budget_id: [],
          bill_id: [],
          foreign_amount: [],
          category: [],
          piggy_bank: [],
          tags: [],
          // custom fields:
          custom_errors: {
            interest_date: [],
            book_date: [],
            process_date: [],
            due_date: [],
            payment_date: [],
            invoice_date: [],
            internal_reference: [],
            notes: [],
            attachments: [],
            external_url: [],
          },
        },
        budget: transaction.budget_id,
        bill: transaction.bill_id,
        tags: newTags,
        custom_fields: {
          interest_date: transaction.interest_date,
          book_date: transaction.book_date,
          process_date: transaction.process_date,
          due_date: transaction.due_date,
          payment_date: transaction.payment_date,
          invoice_date: transaction.invoice_date,
          internal_reference: transaction.internal_reference,
          notes: transaction.notes,
          external_url: transaction.external_url
        },
        foreign_amount: {
          amount: this.roundNumber(this.positiveAmount(transaction.foreign_amount), transaction.foreign_currency_decimal_places),
          currency_id: transaction.foreign_currency_id
        },
        source_account: {
          id: transaction.source_id,
          name: transaction.source_name,
          type: transaction.source_type,
          currency_id: transaction.currency_id,
          currency_name: transaction.currency_name,
          currency_code: transaction.currency_code,
          currency_decimal_places: transaction.currency_decimal_places,
          allowed_types: window.expectedSourceTypes.source[this.ucFirst(transaction.type)]
        },
        destination_account: {
          id: transaction.destination_id,
          name: transaction.destination_name,
          type: transaction.destination_type,
          currency_id: transaction.currency_id,
          currency_name: transaction.currency_name,
          currency_code: transaction.currency_code,
          currency_decimal_places: transaction.currency_decimal_places,
          allowed_types: window.expectedSourceTypes.destination[this.ucFirst(transaction.type)]
        }
      });
    },
    limitSourceType: function (type) {
      // let i;
      // for (i = 0; i < this.transactions.length; i++) {
      //     this.transactions[i].source_account.allowed_types = [type];
      // }
    },
    limitDestinationType: function (type) {
      // let i;
      // for (i = 0; i < this.transactions.length; i++) {
      //     this.transactions[i].destination_account.allowed_types = [type];
      // }
    },
    convertData: function () {
      let data = {
        'apply_rules': this.applyRules,
        'fire_webhooks': this.fireWebhooks,
        'transactions': [],
      };
      let transactionType;
      let firstSource;
      let firstDestination;

      if (this.transactions.length > 1) {
        data.group_title = this.group_title;
      }

      // get transaction type from first transaction
      transactionType = this.transactionType ? this.transactionType.toLowerCase() : 'invalid';

      // if the transaction type is invalid, might just be that we can deduce it from
      // the presence of a source or destination account
      firstSource = this.transactions[0].source_account.type;
      firstDestination = this.transactions[0].destination_account.type;

      if ('invalid' === transactionType && ['Asset account', 'Loan', 'Debt', 'Mortgage'].includes(firstSource)) {
        //console.log('Assumed this is a withdrawal.');
        transactionType = 'withdrawal';
      }

      if ('invalid' === transactionType && ['Asset account', 'Loan', 'Debt', 'Mortgage'].includes(firstDestination)) {
        //console.log('Assumed this is a deposit.');
        transactionType = 'deposit';
      }

      // get currency from first transaction. overrule the rest
      let currencyId = this.transactions[0].source_account.currency_id;

      if ('deposit' === transactionType) {
        currencyId = this.transactions[0].destination_account.currency_id;
      }
      console.log('Overruled currency ID to ' + currencyId);

      for (let key in this.transactions) {
        if (this.transactions.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
          data.transactions.push(this.convertDataRow(this.transactions[key], key, transactionType, currencyId));
        }
      }
      //console.log(data);

      return data;
    },
    convertDataRow(row, index, transactionType, currencyId) {
      let tagList = [];
      let foreignAmount = null;
      let foreignCurrency = null;
      let currentArray;
      let sourceId;
      let sourceName;
      let destId;
      let destName;
      let date;
      sourceId = row.source_account.id;
      sourceName = row.source_account.name;
      destId = row.destination_account.id;
      destName = row.destination_account.name;

      // depends on the transaction type, where we get the currency.
      // if ('withdrawal' === transactionType || 'transfer' === transactionType) {
      //   row.currency_id = row.source_account.currency_id;
      //   console.log('Overruled currency ID to ' + row.currency_id);
      // }
      // if ('deposit' === transactionType) {
      //   row.currency_id = row.destination_account.currency_id;
      //   console.log('Overruled currency ID to ' + row.currency_id);
      // }

      row.currency_id = currencyId;
      console.log('Final currency ID = ' + currencyId);

      date = row.date;
      if (index > 0) {
        date = this.transactions[0].date;
      }

      // if type is 'withdrawal' and destination is empty, cash withdrawal.
      if (transactionType === 'withdrawal' && '' === destName) {
        destId = window.cashAccountId;
      }

      // if type is 'deposit' and source is empty, cash deposit.
      if (transactionType === 'deposit' && '' === sourceName) {
        sourceId = window.cashAccountId;
      }

      // if index is over 0 and type is withdrawal or transfer, take source from index 0.
      if (index > 0 && (transactionType.toLowerCase() === 'withdrawal' || transactionType.toLowerCase() === 'transfer')) {
        sourceId = this.transactions[0].source_account.id;
        sourceName = this.transactions[0].source_account.name;
      }

      // if index is over 0 and type is deposit or transfer, take destination from index 0.
      if (index > 0 && (transactionType.toLowerCase() === 'deposit' || transactionType.toLowerCase() === 'transfer')) {
        destId = this.transactions[0].destination_account.id;
        destName = this.transactions[0].destination_account.name;
      }

      tagList = [];
      foreignAmount = '0';
      // loop tags
      for (let tagKey in row.tags) {
        if (row.tags.hasOwnProperty(tagKey) && /^0$|^[1-9]\d*$/.test(tagKey) && tagKey <= 4294967294) {
          tagList.push(row.tags[tagKey].text);
        }
      }
      // set foreign currency info:
      if (row.foreign_amount.amount !== '' && parseFloat(row.foreign_amount.amount) !== .00) {
        foreignAmount = row.foreign_amount.amount;
        foreignCurrency = row.foreign_amount.currency_id;
      }
      if (foreignCurrency === row.currency_id) {
        foreignAmount = null;
        foreignCurrency = null;
      }

      // correct some id's
      if (0 === destId) {
        destId = null;
      }
      if (0 === sourceId) {
        sourceId = null;
      }

      // parse amount if has exactly one comma:
      // solves issues with some locales.
      if (1 === (String(row.amount).match(/\,/g) || []).length) {
        row.amount = String(row.amount).replace(',', '.');
      }

      currentArray =
          {
            transaction_journal_id: row.transaction_journal_id,
            type: transactionType,
            date: date,
            amount: row.amount,

            description: row.description,

            source_id: sourceId,
            source_name: sourceName,

            destination_id: destId,
            destination_name: destName,


            category_name: row.category,

            interest_date: row.custom_fields.interest_date,
            book_date: row.custom_fields.book_date,
            process_date: row.custom_fields.process_date,
            due_date: row.custom_fields.due_date,
            payment_date: row.custom_fields.payment_date,
            invoice_date: row.custom_fields.invoice_date,
            internal_reference: row.custom_fields.internal_reference,
            external_url: row.custom_fields.external_url,
            notes: row.custom_fields.notes,
            tags: tagList
          };
      // always submit foreign amount info.
      currentArray.foreign_amount = foreignAmount;
      currentArray.foreign_currency_id = foreignCurrency;

      // only submit currency ID when not 0:
      if (0 !== row.currency_id && null !== row.currency_id) {
        currentArray.currency_id = row.currency_id;
      }

      // set budget id and piggy ID.
      currentArray.budget_id = parseInt(row.budget);
      if (parseInt(row.bill) > 0) {
        currentArray.bill_id = parseInt(row.bill);
      }
      if (0 === parseInt(row.bill)) {
        currentArray.bill_id = null;
      }

      if (parseInt(row.piggy_bank) > 0) {
        currentArray.piggy_bank_id = parseInt(row.piggy_bank);
      }

      return currentArray;
    },
    submit: function (e) {

      let button = $('#submitButton');
      button.prop("disabled", true);

      const page = window.location.href.split('/');
      const groupId = page[page.length - 1];
      let uri = './api/v1/transactions/' + groupId + '?_token=' + document.head.querySelector('meta[name="csrf-token"]').content;
      let method = 'PUT';
      if (this.storeAsNew) {
        // other links.
        uri = './api/v1/transactions?_token=' + document.head.querySelector('meta[name="csrf-token"]').content;
        method = 'POST';
      }
      const data = this.convertData();

      //axios.put(uri, data)
      axios({
        method: method,
        url: uri,
        data: data,
      }).then(response => {
        if (0 === this.collectAttachmentData(response)) {
          this.redirectUser(response.data.data.id);
        }
      }).catch(error => {
        // give user errors things back.
        // something something render errors.
        this.parseErrors(error.response.data);
        // something.
      });
      if (e) {
        e.preventDefault();
      }
      button.removeAttr('disabled');
    },

    redirectUser(groupId) {
      if (this.returnAfter) {
        this.setDefaultErrors();
        // do message if update or new:
        if (this.storeAsNew) {
          this.success_message = this.$t('firefly.transaction_new_stored_link', {ID: groupId});
          this.error_message = '';
        } else {
          this.success_message = this.$t('firefly.transaction_updated_link', {ID: groupId});
          this.error_message = '';
        }
      } else {
        if (this.storeAsNew) {
          window.location.href = window.previousUrl + '?transaction_group_id=' + groupId + '&message=created';
        } else {
          window.location.href = window.previousUrl + '?transaction_group_id=' + groupId + '&message=updated';
        }
      }
    },

    collectAttachmentData(response) {
      // console.log('Now incollectAttachmentData()');
      let groupId = response.data.data.id;

      // array of all files to be uploaded:
      let toBeUploaded = [];

      // array with all file data.
      let fileData = [];

      // all attachments
      let attachments = $('input[name="attachments[]"]');

      // loop over all attachments, and add references to this array:
      for (const key in attachments) {
        if (attachments.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
          for (const fileKey in attachments[key].files) {
            if (attachments[key].files.hasOwnProperty(fileKey) && /^0$|^[1-9]\d*$/.test(fileKey) && fileKey <= 4294967294) {
              // include journal thing.

              let transactions = response.data.data.attributes.transactions.reverse();

              toBeUploaded.push(
                  {
                    journal: transactions[key].transaction_journal_id,
                    file: attachments[key].files[fileKey]
                  }
              );
            }
          }
        }
      }
      let count = toBeUploaded.length;
      // console.log('Found ' + toBeUploaded.length + ' attachments.');

      // loop all uploads.
      for (const key in toBeUploaded) {
        if (toBeUploaded.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
          // create file reader thing that will read all of these uploads
          (function (f, i, theParent) {
            let fileReader = new FileReader();
            fileReader.onloadend = function (evt) {
              if (evt.target.readyState === FileReader.DONE) { // DONE == 2
                fileData.push(
                    {
                      name: toBeUploaded[key].file.name,
                      journal: toBeUploaded[key].journal,
                      content: new Blob([evt.target.result])
                    }
                );
                if (fileData.length === count) {
                  theParent.uploadFiles(fileData, groupId);
                }
              }
            };
            fileReader.readAsArrayBuffer(f.file);
          })(toBeUploaded[key], key, this);
        }
      }
      return count;
    },

    uploadFiles(fileData, groupId) {
      let count = fileData.length;
      let uploads = 0;
      for (const key in fileData) {
        if (fileData.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
          // console.log('Creating attachment #' + key);
          // axios thing, + then.
          const uri = './api/v1/attachments';
          const data = {
            filename: fileData[key].name,
            attachable_type: 'TransactionJournal',
            attachable_id: fileData[key].journal,
          };
          axios.post(uri, data)
              .then(response => {
                // console.log('Created attachment #' + key);
                // console.log('Uploading attachment #' + key);
                const uploadUri = './api/v1/attachments/' + response.data.data.id + '/upload';
                axios.post(uploadUri, fileData[key].content)
                    .then(secondResponse => {
                      // console.log('Uploaded attachment #' + key);
                      uploads++;
                      if (uploads === count) {
                        // finally we can redirect the user onwards.
                        // console.log('FINAL UPLOAD');
                        this.redirectUser(groupId, null);
                      }
                      // console.log('Upload complete!');
                      return true;
                    }).catch(error => {
                  console.error('Could not upload file.');
                  console.error(error);
                  uploads++;
                  this.error_message = 'Could not upload attachment: ' + error;
                  if (uploads === count) {
                    this.redirectUser(groupId, null);
                  }
                  // console.error(error);
                  return false;
                });
              }).catch(error => {
            console.error('Could not create upload.');
            console.error(error);
            uploads++;
            if (uploads === count) {
              // finally we can redirect the user onwards.
              // console.log('FINAL UPLOAD');
              this.redirectUser(groupId, null);
            }
            // console.log('Upload complete!');
            return false;
          });
        }
      }

    },


    addTransaction: function (e) {

      this.transactions.push({
        transaction_journal_id: 0,
        description: "",
        date: "",
        amount: "",
        category: "",
        piggy_bank: 0,
        errors: {
          source_account: [],
          destination_account: [],
          description: [],
          amount: [],
          date: [],
          budget_id: [],
          bill_id: [],
          foreign_amount: [],
          category: [],
          piggy_bank: [],
          tags: [],
          // custom fields:
          custom_errors: {
            interest_date: [],
            book_date: [],
            process_date: [],
            due_date: [],
            payment_date: [],
            invoice_date: [],
            internal_reference: [],
            notes: [],
            attachments: [],
            external_url: [],
          },
        },
        budget: 0,
        bill: 0,
        tags: [],
        custom_fields: {
          "interest_date": "",
          "book_date": "",
          "process_date": "",
          "due_date": "",
          "payment_date": "",
          "invoice_date": "",
          "internal_reference": "",
          "notes": "",
          "attachments": [],
          "external_url": "",
        },
        foreign_amount: {
          amount: "",
          currency_id: 0
        },
        source_account: {
          id: 0,
          name: "",
          type: "",
          currency_id: 0,
          currency_name: '',
          currency_code: '',
          currency_decimal_places: 2,
          allowed_types: []
        },
        destination_account: {
          id: 0,
          name: "",
          type: "",
          currency_id: 0,
          currency_name: '',
          currency_code: '',
          currency_decimal_places: 2,
          allowed_types: []
        }
      });
      let count = this.transactions.length;
      // console.log('Transactions length = ' + count);
      // also set accounts from previous entry, if present.
      if (this.transactions.length > 1) {
        // console.log('Adding split.');
        this.transactions[count - 1].source_account = this.transactions[count - 2].source_account;
        this.transactions[count - 1].destination_account = this.transactions[count - 2].destination_account;
        this.transactions[count - 1].date = this.transactions[count - 2].date;
      }
      // console.log('Transactions length now = ' + this.transactions.length);

      if (e) {
        e.preventDefault();
      }
    },
    parseErrors: function (errors) {
      this.setDefaultErrors();
      this.error_message = "";
      if (errors.message.length > 0) {
        this.error_message = this.$t('firefly.errors_submission');
      } else {
        this.error_message = '';
      }
      let transactionIndex;
      let fieldName;

      for (const key in errors.errors) {
        if (errors.errors.hasOwnProperty(key)) {
          if (key === 'group_title') {
            this.group_title_errors = errors.errors[key];
          }
          if (key !== 'group_title') {
            // lol dumbest way to explode "transactions.0.something" ever.
            transactionIndex = parseInt(key.split('.')[1]);
            fieldName = key.split('.')[2];
            // set error in this object thing.
            switch (fieldName) {
              case 'amount':
              case 'date':
              case 'budget_id':
              case 'bill_id':
              case 'description':
              case 'tags':
                this.transactions[transactionIndex].errors[fieldName] = errors.errors[key];
                break;
              case 'external_url':
                //console.log('Found ext error in field "' + fieldName + '": ' + errors.errors[key]);
                this.transactions[transactionIndex].errors.custom_errors[fieldName] = errors.errors[key];
                break;
              case 'source_name':
              case 'source_id':
                this.transactions[transactionIndex].errors.source_account =
                    this.transactions[transactionIndex].errors.source_account.concat(errors.errors[key]);
                break;
              case 'destination_name':
              case 'destination_id':
                this.transactions[transactionIndex].errors.destination_account =
                    this.transactions[transactionIndex].errors.destination_account.concat(errors.errors[key]);
                break;
              case 'foreign_amount':
              case 'foreign_currency_id':
                this.transactions[transactionIndex].errors.foreign_amount =
                    this.transactions[transactionIndex].errors.foreign_amount.concat(errors.errors[key]);
                break;
            }

            // unique some things
            this.transactions[transactionIndex].errors.source_account =
                Array.from(new Set(this.transactions[transactionIndex].errors.source_account));
            this.transactions[transactionIndex].errors.destination_account =
                Array.from(new Set(this.transactions[transactionIndex].errors.destination_account));
          }
        }
      }
    },
    setDefaultErrors: function () {
      for (const key in this.transactions) {
        if (this.transactions.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
          this.transactions[key].errors = {
            source_account: [],
            destination_account: [],
            description: [],
            amount: [],
            date: [],
            budget_id: [],
            bill_id: [],
            foreign_amount: [],
            category: [],
            piggy_bank: [],
            tags: [],
            // custom fields:
            custom_errors: {
              interest_date: [],
              book_date: [],
              process_date: [],
              due_date: [],
              payment_date: [],
              invoice_date: [],
              internal_reference: [],
              notes: [],
              attachments: [],
              external_url: [],
            },
          };
        }
      }
    },
  },


  data() {
    return {
      applyRules: true,
      fireWebhooks: true,
      group: this.groupId,
      error_message: "",
      success_message: "",
      transactions: [],
      group_title: "",
      returnAfter: false,
      storeAsNew: false,
      transactionType: null,
      group_title_errors: [],
      resetButtonDisabled: true,
    }
  }
}
</script>
